package MeteoCal.manager;

import MeteoCal.entity.Event;
import MeteoCal.entity.Invitation;
import MeteoCal.entity.Notification;
import MeteoCal.entity.Receivednotification;
import MeteoCal.entity.Schedule;
import MeteoCal.entity.User;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.TypedQuery;

/**
 *
 * @authors Guttadoro, Iommazzo, Saullo
 */
@Stateless
public class EventManager {

    @PersistenceContext
    private EntityManager em;
    @EJB
    private WeatherManager wm;
    @EJB
    private NotificationManager nm;
    @EJB 
    private InvitationManager im;
    
    public Boolean createEvent(Event event, User u){
      
        if(overlapping(u, event)== null){
            event.setIdCreator(u);
            eventsinSchedule(event,u);
            
            em.persist(event);
            if(wm.findWeatherByCityAndDate(event.getCity(), event.getDateBegin()).isEmpty())
                wm.createWeather(event);
            return true;
        }
        
        return false;
    }
    
    private void eventsinSchedule(Event event, User user){
        List<Schedule> listSchedule = new ArrayList<>();
        listSchedule.add(em.find(Schedule.class, user.getIdSchedule().getIdSchedule()));
        event.setScheduleCollection(listSchedule);
    }
    
    public Event overlapping (User user, Event item){
        
        Collection<Event> list = this.getAllEvents(user);

        Date edatebeg = item.getDateBegin();
        Date edateend = item.getDateEnd();
        System.out.println("Datebeg " + edatebeg.toString()+ " dateend " + edateend.toString());
        for(Event it: list){
            if(item.getIdEvent() != null){
                if(it.getIdEvent() == item.getIdEvent()){
                    continue;
                }
            }
            Date ldatebeg = it.getDateBegin();
            Date ldateend = it.getDateEnd();
            System.out.println("Datebeg " + ldatebeg.toString()+ " dateend " + ldateend.toString());
            if((edatebeg.after(ldatebeg) && edatebeg.before(ldateend)) ||
                (edateend.after(ldatebeg) && edateend.before(ldateend)) ||
                (edatebeg.before(ldatebeg) && edateend.after(ldateend)) ||
                (edatebeg.equals(ldatebeg) || edateend.equals(ldateend)))
            return it;
        }
        return null;
    }
   
     public void remove(Event entity) {
        em.remove(em.merge(entity));
    }
    
     public void edit(Event event) {
        Query prova = em.createNativeQuery("UPDATE event SET DateBegin = ? WHERE (idEvent = ?)");
        prova.setParameter("DateBegin",event.getDateBegin());
        prova.setParameter("idEvent",event.getIdEvent());
        Query prova2 = em.createNativeQuery("UPDATE event SET DateEnd = ? WHERE (idEvent = ?)");
        prova2.setParameter("DateEnd",event.getDateEnd());
        prova2.setParameter("idEvent",event.getIdEvent()); 
    }
     
    //We obtain the list of all events linked to a user
    public Collection<Event> getAllEvents(User user){
        
        //I look for all events related to his own idschedule
        Schedule schedule = this.getSchedulebyId(user); 
        em.refresh(schedule);
        System.err.println("Schedule --> " + schedule.getIdSchedule());
        return eventsChangeDate(schedule.getEventCollection());
    }
    
    private Schedule getSchedulebyId(User user) {
    
        TypedQuery<Schedule> query2 = em.createNamedQuery("Schedule.findByIdSchedule", Schedule.class);
        query2.setParameter("idSchedule", user.getIdSchedule().getIdSchedule());
        return query2.getSingleResult();
    }
    
    private Collection<Event> eventsChangeDate(Collection<Event> events) {
        
        List<Event> result = new ArrayList<>() ;
        System.err.println("Event .... "+ events.toString());
        for(Event e : events){
            Calendar cBegin = Calendar.getInstance();
            cBegin.setTime(e.getDateBegin());
            cBegin.set(Calendar.HOUR_OF_DAY, e.getHourBegin().getHours());
            cBegin.set(Calendar.MINUTE,e.getHourBegin().getMinutes());
            cBegin.set(Calendar.SECOND, 0);
            cBegin.set(Calendar.MILLISECOND, 0);
            System.err.println("CBEGIN  " + cBegin.getTime().toString());
            Calendar cEnd = Calendar.getInstance();
            cEnd.setTime(e.getDateEnd());
            cEnd.set(Calendar.HOUR_OF_DAY, e.getHourEnd().getHours());
            cEnd.set(Calendar.MINUTE,e.getHourEnd().getMinutes());
            cEnd.set(Calendar.SECOND, 0);
            cEnd.set(Calendar.MILLISECOND, 0);
            System.err.println("CEND " + cEnd.getTime().toString());
            Event enew = new Event(e);
            enew.setDateBegin(cBegin.getTime());
            enew.setDateEnd(cEnd.getTime());
           // Event enew2 = new Event(e.getName(),e.getCity(),e.getAddress(),e.getDescription(),cBegin.getTime(),cEnd.getTime(),e.getPublic1(),e.getOutdoor());
            result.add(enew);
        }
        return result;
    }
    /*ALE*/
    
    public Event getEvent(Integer id) {
        
        return em.find(Event.class, id);
             
       /* TypedQuery<Event> query = em.createNamedQuery("Event.findByIdEvent", Event.class);
        query.setParameter("idEvent", id);
        Event result = query.getSingleResult();
        
        return result;*/
    }
    
    public ArrayList<Event> getEventsList(String name, String city) {     //<!Prototype>
        
        TypedQuery<Event> query;
        ArrayList<Event> result;
        
        if (!name.isEmpty()){
            query = em.createNamedQuery("Event.findByName", Event.class);
            query.setParameter("name", name);
            result = (ArrayList<Event>) query.getResultList();
        }  
        else if (!city.isEmpty()){
            query = em.createNamedQuery("Event.findByCity", Event.class);
            query.setParameter("city", city);
            result = (ArrayList<Event>) query.getResultList();
            }                
           /* else if (dateBegin != null){
                query = em.createNamedQuery("Event.findByDateBegin", Event.class);
                query.setParameter("dateBegin", dateBegin);
                result = query.getResultList();
                }      
                else if (idCreator != -1){
                    
                    Query q = em.createNativeQuery("SELECT e FROM Event e WHERE e.idCreator.idUser = :idCreator.idUser", Event.class);
                    q.setParameter("idCreator.idUser", idCreator);
                    result = q.getResultList();
                    
                    }   */      
                    /* Errore */
                    else return null; 
        
        return result;
    }

    public Boolean updateEvent(User u, Event e) {
        
        if(overlapping(u,e)== null){
            em.merge(e);
            em.flush();
            return true;
        }
        
        return false;
        
        
    }

//    public void refreshStatus(Event e) {
//        em.refresh(e);
//    }

    public void removeEvent(Event e) {
        Event event = em.find(Event.class, e.getIdEvent());
        Collection<Notification> notifications = event.getNotificationCollection();
        for(Notification n: notifications){
            Collection<Receivednotification> recnotifications = n.getReceivednotificationCollection();
            for (Receivednotification rn: recnotifications){
                em.remove(rn);
            }
            em.remove(n);
        }
        Collection<Invitation> invitations = event.getInvitationCollection();
        for(Invitation i : invitations) {
            em.remove(i);
        }
               
        em.remove(event);
        em.flush();
    }
    
    public List<Event> search(String searchString) {
        return this.getEventByName(searchString);
        
    }
    
    private List<Event> getEventByName(String name){
        TypedQuery<Event> query = em.createNamedQuery("Event.findByName", Event.class);
        query.setParameter("name", name);
        List<Event> l = query.getResultList();
        return l;
    }
    
    public List<Event> getAllEvents(){
        return em.createNamedQuery("Event.findAll", Event.class).getResultList();
    }
}
